package com.dnjn.happiness.system.controller;

import com.baomidou.mybatisplus.core.toolkit.Assert;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.dnjn.happiness.common.core.utils.DateUtils;
import com.dnjn.happiness.common.core.utils.StringUtils;
import com.dnjn.happiness.common.core.utils.bean.BeanUtils;
import com.dnjn.happiness.common.cloud.controller.BaseController;
import com.dnjn.happiness.common.core.web.domain.AjaxResult;
import com.dnjn.happiness.common.log.annotation.Log;
import com.dnjn.happiness.common.log.enums.BusinessType;
import com.dnjn.happiness.common.security.annotation.RequiresPermissions;
import com.dnjn.happiness.common.security.utils.SecurityUtils;
import com.dnjn.happiness.system.api.domain.SysTeam;
import com.dnjn.happiness.system.api.domain.SysUser;
import com.dnjn.happiness.system.domain.PositionLadder;
import com.dnjn.happiness.system.domain.SysPost;
import com.dnjn.happiness.system.domain.vo.SysTeamVO;
import com.dnjn.happiness.system.domain.vo.TeamLineChartDataVO;
import com.dnjn.happiness.system.domain.vo.TeamLineChartVO;
import com.dnjn.happiness.system.domain.vo.TeamScoreSpreadVO;
import com.dnjn.happiness.system.domain.vo.TeamUserSituationVO;
import com.dnjn.happiness.system.enums.BindType;
import com.dnjn.happiness.system.service.ISysConfigService;
import com.dnjn.happiness.system.service.ISysPostService;
import com.dnjn.happiness.system.service.ISysTeamService;
import com.dnjn.happiness.system.service.ISysUserService;
import com.dnjn.happiness.system.service.impl.QrCodeService;
import com.dnjn.happiness.system.util.GenerateInviteCode;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;


import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * 人员架构Controller
 * 
 * @author amber
 * @date 2024-01-02
 */
@Tag(name = "sys sysTeam 人员架构", description = "人员架构")
@RestController
@RequestMapping("/sysTeam")
public class SysTeamController extends BaseController
{
    @Autowired
    private ISysTeamService sysTeamService;

    @Autowired
    private QrCodeService codeService;

    @Autowired
    private ISysUserService userService;

    @Autowired
    private GenerateInviteCode generateInviteCode;

    @Autowired
    private ISysPostService postService;

    @Autowired
    private ISysConfigService configService;


    /**
     * 查询人员架构列表
     */
    //@RequiresPermissions("@ss.hasPermi('sys:sysTeam:list')")
    @PostMapping("/list")
    @Log(title = "sys", businessType = BusinessType.LIST)
    public AjaxResult list(@RequestBody SysTeamVO vo, @RequestParam(defaultValue = "1") Integer current, @RequestParam(defaultValue = "10") Integer size) {
        SysTeam sysTeam = new SysTeam();
        BeanUtils.copyPropsIgnoreNull(vo, sysTeam);
        Page page = Page.of(current, size);
        Page<SysTeam> list = sysTeamService.page(page, Wrappers.query(sysTeam));
        return success(list);
    }

    /**
     * 获取人员架构详细信息
     */
    //@RequiresPermissions("@ss.hasPermi('sys:sysTeam:query')")
    @GetMapping(value = "/{teamId}")
    @Log(title = "biz", businessType = BusinessType.SELECT)
    public AjaxResult get(@PathVariable("teamId") Long teamId) {
        return success(sysTeamService.getById(teamId));
    }

    /**
     * 新增人员架构
     */
    @Log(title = "人员架构", businessType = BusinessType.INSERT)
    //@RequiresPermissions("@ss.hasPermi('sys:sysTeam:add')")
    @PostMapping("/add")
    public AjaxResult add(@RequestBody SysTeamVO vo) {
        SysTeam sysTeam = new SysTeam();
        BeanUtils.copyPropsIgnoreNull(vo, sysTeam);

        sysTeam.setCreateBy(SecurityUtils.getUsername());
        return toAjax(sysTeamService.save(sysTeam));
    }

    /**
     * 修改人员架构
     */
    @Log(title = "人员架构", businessType = BusinessType.UPDATE)
    //@RequiresPermissions("@ss.hasPermi('sys:sysTeam:edit')")
    @PutMapping("/edit")
    public AjaxResult edit(@RequestBody SysTeamVO vo) {
        SysTeam sysTeam = new SysTeam();
        BeanUtils.copyPropsIgnoreNull(vo, sysTeam);
        return toAjax(sysTeamService.updateById(sysTeam));
    }

    /**
     * 删除人员架构
     */
    @Log(title = "人员架构", businessType = BusinessType.DELETE)
    //@RequiresPermissions("@ss.hasPermi('sys:sysTeam:remove')")
    @DeleteMapping("/{teamIds}")
    public AjaxResult remove(@PathVariable Long[] teamIds) {
        return toAjax(sysTeamService.removeBatchByIds(Arrays.asList(teamIds)));
    }


    /**
     * 根据用户Id,获取人员架构详细信息
     */
    @GetMapping(value = "/getInfoByUserId/{userId}")
    @Log(title = "biz", businessType = BusinessType.SELECT)
    public AjaxResult getInfoByUserId(@PathVariable("userId") Long userId) {
        return sysTeamService.getInfoByUserId(userId);
    }


    /**
     * 邀请码绑定
     * 根据邀请码绑定上级，组级
     * 只传邀请码就行了 userId可以传可以不传
     */
    @PutMapping("/inviteCodeBind/{inviteCode}")
    public AjaxResult inviteCodeBind(@PathVariable String inviteCode) {
        Map<String, Object> map = sysTeamService.inviteCodeBind(new SysTeamVO().setInviteCode(inviteCode));
        String mes = (String) map.get("mes");
        if (StringUtils.isEmpty(mes)) {
            return AjaxResult.success(map.get("team"));
        } else {
            return AjaxResult.error(mes);
        }
    }


    /**
     * 解绑
     */
    /**
     * 邀请码绑定
     * 根据邀请码绑定上级，组级
     * MULTIPOINT 多点解绑
     * SINGLEPOINT 单点解绑
     */
    @PutMapping("/unBind")
    @RequiresPermissions("@ss.hasAnyPermi('sys:sysTeam:edit,ignore:sysTeam:edit')")
    public AjaxResult unBind(@RequestParam Long userId, @Parameter(description = "MULTIPOINT 多点解绑 | SINGLEPOINT 单点解绑") @RequestParam BindType unBindType) {

        return sysTeamService.unBind(new SysTeamVO().setUserId(userId).setUnBindType(unBindType));
    }

    //生成二维码流并将其返回给前端调用者
//    @PostMapping("/generateCode")
    public AjaxResult generateCode(/*String content,*/ HttpServletResponse servletResponse) {
        String codeBase64 = null;
        try {
            Long userId = SecurityUtils.getUserId();
            SysTeam sysTeam = sysTeamService.getTeamByUserId(userId);
            if (null != sysTeam && !StringUtils.isEmpty(sysTeam.getInviteCode())) {
                //将生成的二维码文件直接返回给前端响应流
                codeBase64 = QrCodeService.getQRCodeBase64(sysTeam.getInviteCode(), 300, 300);
            } else {
                SysUser sysUser = userService.selectUserInfo(userId);
                if (null != sysUser && null == sysTeam) {
                    String inviteCode = generateInviteCode.getInviteCode();
                    //创建一个team记录
                    SysTeam team = new SysTeam().setUserId(userId).setInviteCode(inviteCode);
                    sysTeamService.save(team);
                    //将生成的二维码文件直接返回给前端响应流
                    codeBase64 = QrCodeService.getQRCodeBase64(sysTeam.getInviteCode(), 300, 300);
                } else {
                    return AjaxResult.error("当前登录用户信息查询失败");
                }
            }
        } catch (Exception e) {
            return AjaxResult.error("生成二维码失败");
        }
        return AjaxResult.success().put("codeBase64", codeBase64);
    }





    /**
     * 根据用户id查询我的团队列表第一层 perentId
     */
    @PostMapping(value = "/getTeamListByUserIdAndParentId/{userId}")
    @Log(title = "biz", businessType = BusinessType.SELECT)
    public AjaxResult getTeamListByUserIdAndParentId(@PathVariable Long userId, @RequestParam(required = false) String nickName) {
        Assert.notNull(userId, "当前登录用户Id不能为空！");
        return sysTeamService.getTeamListByUserIdAndParentId(userId, nickName);
    }




    /**
     * 查询当前用户部门下的所有用户岗位列表
     */
    @Operation(summary = "查询当前用户部门下的所有用户岗位列表")
    @GetMapping("/getAllPostList")
    @Log(title = "biz", businessType = BusinessType.SELECT)
    public AjaxResult getAllPostList() {
        Long userId = SecurityUtils.getUserId();
        SysTeam currTeam = sysTeamService.getTeamByUserId(userId);
        List<SysPost> postList = new ArrayList<>();
        if (null != currTeam) {
            postList = postService.queryPostListByTeamId(currTeam.getTeamId());
        }
        return AjaxResult.success(postList);
    }


    /**
     * 根据postId岗位id查询当前用户部门下该岗位的用户列表 - 小程序
     */
    @Operation(summary = "根据postId岗位id查询当前用户下该岗位用户列表-nickName模糊搜索")
    @PostMapping("/getUsersByPostId")
    @Log(title = "biz", businessType = BusinessType.SELECT)
    public AjaxResult getUsersByPostId(@RequestParam Long postId, @RequestParam(required = false) String nickName) {
        Assert.notNull(postId, "岗位Id不能为空");
        List<SysUser> userList = new ArrayList<>();
        if (ObjectUtils.isEmpty(postId)) {
            return AjaxResult.success(userList);
        }
        Map<String, Object> map = new HashMap<>();
        map.put("postId", postId);
        map.put("nickName", nickName);
        Long userId = SecurityUtils.getUserId();
        SysTeam currTeam = sysTeamService.getTeamByUserId(userId);
        if (null != currTeam) {
            map.put("teamId", currTeam.getTeamId());
            userList = userService.getUsersByPostIdAndTeamId(map);
        }
        return AjaxResult.success(userList);
    }

    /**
     * 查询职级列表 - 小程序
     */
    @Operation(summary = "查询职级列表")
    @GetMapping("/getPositionLadderList")
    @Log(title = "biz", businessType = BusinessType.SELECT)
    public AjaxResult getPositionList() {

        Long userId = SecurityUtils.getUserId();
        SysTeam currTeam = sysTeamService.getTeamByUserId(userId);
        List<PositionLadder> list = new ArrayList<>();
        if (null != currTeam) {
            list = sysTeamService.queryPositionListByTeamId(currTeam.getTeamId());
        }
        return AjaxResult.success(list);
    }

    /**
     * 根据职级查询当前用户部门下该职级的用户列表 - 小程序
     */
    @Operation(summary = "根据职级查询当前用户下该职级的用户列表-nickName模糊搜索")
    @PostMapping("/getUsersByPositionCode")
    @Log(title = "biz", businessType = BusinessType.SELECT)
    public AjaxResult getUsersByPositionCode(@RequestParam String position, @RequestParam(required = false) String nickName) {
        Assert.notNull(position, "职级不能为空");
        List<SysUser> userList = new ArrayList<>();
        if (StringUtils.isEmpty(position)) {
            return AjaxResult.success(userList);
        }
        Map<String, Object> map = new HashMap<>();
        map.put("position", position);
        map.put("nickName", nickName);
        Long userId = SecurityUtils.getUserId();
        SysTeam currTeam = sysTeamService.getTeamByUserId(userId);
        if (null != currTeam) {
            map.put("teamId", currTeam.getTeamId());
            userList = sysTeamService.getUsersByPositionAndTeamId(map);
        }
        return AjaxResult.success(userList);
    }

    /**
     * 递归查询所有有下级的团队
     */
    @Operation(summary = "getTeamReportForms 查询所有有下级的团队")
    @PostMapping("/getTeamReportForms")
    @Log(title = "biz", businessType = BusinessType.SELECT)
    public AjaxResult getTeamReportForms(@RequestParam(required = false) String nickName, @RequestParam(required = false) Long deptId) {
        if (Objects.isNull(deptId)) {
            deptId = SecurityUtils.getLoginUser().getDeptId();
        }
        AjaxResult ajaxResult = sysTeamService.getTeamReportForms(nickName, deptId);
        return ajaxResult;
    }

    /**
     * 查询当前团队下的人员柱状图
     */
    @Operation(summary = "查询当前团队下的人员柱状图")
    @PostMapping("/getTeamIntervalChart")
    @Log(title = "biz", businessType = BusinessType.SELECT)
    public AjaxResult getTeamIntervalChart(@RequestParam(required = true) Long teamId, @RequestParam(required = false) String weekOfYear) {
        Assert.notNull(teamId, "团队ID不能为空!");
        List<Long> longList = sysTeamService.recursionTeam(teamId);

        List<TeamScoreSpreadVO> list = new ArrayList<>();
        list.add(new TeamScoreSpreadVO().setStartInterval(300).setEndInterval(400));
        list.add(new TeamScoreSpreadVO().setStartInterval(400).setEndInterval(500));
        list.add(new TeamScoreSpreadVO().setStartInterval(500).setEndInterval(600));
        list.add(new TeamScoreSpreadVO().setStartInterval(600).setEndInterval(700));
        list.add(new TeamScoreSpreadVO().setStartInterval(700).setEndInterval(800));
        list.add(new TeamScoreSpreadVO().setStartInterval(800).setEndInterval(900));
        //查询沟通临界值。
        String configValueByKey = configService.getConfigValueByKey("biz.happinessScore.threshold");
        if (StringUtils.isEmpty(configValueByKey)) {
            return AjaxResult.error("快乐值临界值为空！");
        }
        //构建柱状图数据
        for (TeamScoreSpreadVO vo : list) {
            vo.setRequiredCommunicateCount(sysTeamService.queryRequiredCommunicateCount(vo.getStartInterval(), vo.getEndInterval(), Integer.parseInt(configValueByKey), longList));
            vo.setNormalCount(sysTeamService.queryNormalCount(vo.getStartInterval(), vo.getEndInterval(), Integer.parseInt(configValueByKey), longList));
            vo.setTotalCount(vo.getRequiredCommunicateCount() + vo.getNormalCount());
        }
        //查询有几个周的数据，前端显示多少周
        List<TeamLineChartVO> weekList = sysTeamService.getWeekList();
        if (!CollectionUtils.isEmpty(weekList) && StringUtils.isNotEmpty(weekList.get(0).getWeek())) {
            int i = Integer.parseInt(weekList.get(0).getWeek());
            for (int j = i - 1; j >= 1; j--) {
                TeamLineChartVO vo = new TeamLineChartVO();
                vo.setWeek(String.valueOf(j));
                weekList.add(0, vo);
            }

        }

        return new AjaxResult().put("histogramDataList", list).put("weekList", weekList);
    }


    /**
     * 查询当前团队下的人员分布情况
     */
    @Operation(summary = "查询当前团队下的人员分布情况")
    @PostMapping("/getUserListByTeam")
    @Log(title = "biz", businessType = BusinessType.SELECT)
    public AjaxResult getUserListByTeam(@RequestParam(required = true) Long teamId,
                                        @RequestParam(defaultValue = "1") Integer current, @RequestParam(defaultValue = "10") Integer size,
                                        @Parameter(description = "展示类型：需沟通类型（communicate）| 正常类型(normal)") @RequestParam(value = "showType", required = false) String showType,
                                        @RequestParam(required = false) String startInterval,
                                        @RequestParam(required = false) String endInterval) {
        Assert.notNull(teamId, "团队ID不能为空!");
        Page page = Page.of(current, size);
        //构建人员列表
        List<Long> longList = sysTeamService.recursionTeam(teamId);
        HashMap<String, Object> map = new HashMap<>();
        map.put("longList", longList);

        //如果区间不为空，则查询当前团队下区间的人员列表
        if (StringUtils.isNotNull(startInterval) && StringUtils.isNotNull(endInterval)) {
            map.put("startInterval", startInterval);
            map.put("endInterval", endInterval);
        }
        String criticalValueStr = configService.getConfigValueByKey("biz.happinessScore.threshold");
        //临界值
        int criticalValue = Integer.parseInt(criticalValueStr);
        if (StringUtils.isNotEmpty(showType)) {
            map.put("showType", showType);
            map.put("threshold", criticalValue);
        }
        Integer requiredCommunicateCount = sysTeamService.queryRequiredCommunicateCount(Integer.valueOf(startInterval), Integer.valueOf(endInterval), Integer.parseInt(criticalValueStr), longList);
        Page<TeamUserSituationVO> list = sysTeamService.getGraphicReportsPage(page, map);
        //设置状态，快乐之波动
        for (TeamUserSituationVO vo : list.getRecords()) {
            vo.setRequiredCommunicateCount(requiredCommunicateCount);
            Long currScore = vo.getHappinessScore();
            Long userId = vo.getUserId();
            //查询较昨日波动
            BigDecimal yesterdayScoreAvg = sysTeamService.selectYesterdayScoreAvgByUserId(userId);
            //快乐值波动
            if (StringUtils.isNull(yesterdayScoreAvg)) {
                vo.setHappinessScoreChange(0L);
            } else {
                vo.setHappinessScoreChange(currScore - yesterdayScoreAvg.longValue());
            }
            //查询当前状态 先判断当前快乐值是否是需要沟通
            if (currScore < criticalValue) {
                Integer value = sysTeamService.selectDaysByUserId(userId);
                vo.setStatus(StringUtils.isNull(value) || value == 0 ? "需沟通" : "延迟" + value + "天");
            } else {
                vo.setStatus("正常");
            }

            //是否评价，
            LocalDateTime appraiseTime = vo.getAppraiseTime();
            if (Objects.isNull(appraiseTime)) {
                vo.setHasAppraise(true);
            } else {
                LocalDateTime now = LocalDateTime.now();
                Duration duration = Duration.between(now, appraiseTime);
                if (Math.abs(duration.toDays()) >= 7) {
                    vo.setHasAppraise(true);
                } else {
                    LocalDateTime plusDays = appraiseTime.plusDays(7);
                    duration = Duration.between(now, plusDays);
                    vo.setHasAppraise(false);
                    vo.setCountdown(Math.abs(duration.toDaysPart()) + "天" + Math.abs(duration.toHoursPart()) + "时" + Math.abs(duration.toMinutesPart()) + "分后可评价");
                }
            }

        }
        return AjaxResult.success(list);
    }

    /**
     * 查询当前团队 下级管理者，根据周
     */
    @Operation(summary = "查询当前团队下级管理者数据")
    @PostMapping("/getLowerLevelManagers")
    @Log(title = "biz", businessType = BusinessType.SELECT)
    public AjaxResult getLowerLevelManagers(@RequestParam(required = true) Long teamId, @RequestParam(required = false) String weekOfYear) {
        Assert.notNull(teamId, "团队ID不能为空!");
        List<Long> longList = sysTeamService.recursionTeam(teamId);

        //当前管理者下得多折线图数据(直属下级管理人员的日均值,一次显示一周的)
        List<SysTeam> childList = sysTeamService.lambdaQuery().eq(SysTeam::getDeleted, "0").eq(SysTeam::getParentId, teamId).list();
        List<Long> userIdList = new ArrayList<>();
        for (SysTeam child : childList) {
            if (longList.contains(child.getUserId())) {
                userIdList.add(child.getUserId());
            }
        }
        //如果周数为空，查询当前周
        int week = DateUtils.getWeek();
        //当前年数
        int year = DateUtils.getYear();
        if (!StringUtils.isEmpty(weekOfYear)) {
            week = Integer.valueOf(weekOfYear);
        }
        weekOfYear = String.format("%04d%02d", year, week);


        //折线图数据
        List<TeamLineChartDataVO> lineChartDataList = new ArrayList<>();
        for (Long userId : userIdList) {
            List<TeamLineChartVO> list = sysTeamService.selectDataByWeek(weekOfYear, userId);
            if (!CollectionUtils.isEmpty(list)) {
                TeamLineChartDataVO chartDataVO = new TeamLineChartDataVO()
                        .setNickName(list.get(0).getNickName())
                        .setUserId(list.get(0).getUserId());
                List<TeamLineChartDataVO.Data> dataList = new ArrayList<>();
                for (TeamLineChartVO vo : list) {
                    TeamLineChartDataVO.Data data = new TeamLineChartDataVO.Data()
                            .setScoreAvg(vo.getScoreAvg())
                            .setWeek(vo.getWeek());
                    dataList.add(data);
                }
                chartDataVO.setData(dataList);
                lineChartDataList.add(chartDataVO);
            }

        }


        return AjaxResult.success(lineChartDataList);

    }




}
